// Decompiled by Jad v1.5.8g. Copyright 2001 Pavel Kouznetsov.
// Jad home page: http://www.kpdus.com/jad.html
// Decompiler options: packimports(3) 

package it.softphone.commons.util.web.proxy;

import static it.softphone.commons.util.LogUtil.logger;

import java.io.IOException;
import java.util.Enumeration;
import java.util.Hashtable;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 
 */
public class HttpProxyServlet extends HttpServlet
{
    public static final String HOST_PARAM = "host";
	public static final String IGNORE_CONTENT_TYPE_PARAM = "ignoreContentType";
	public static final String TIMEOUT_PARAM 		= "timeout";
	public static final String GZIP_PARAM 			= "gzip";
	public static final String HEADERS_PARAM 		= "headers";
	public static final String URI_PARAM 			= "uri";
	public static final String ENCODING_PARAM 		= "encoding";
	public static final String REWRITE_HOST_PARAM 	= "rewriteHost";
	public static final String PROXY_PORT_PARAM 	= "proxyPort";
	public static final String PROXY_HOST_PARAM 	= "proxyHost";
	
	private String hostName;
    private String proxyHost;
    private String proxyPort;
    private String rewriteHost;
    private String encoding;
    private String keepHeaders;
    private String uri;
    private String disableAcceptEncoding;
    private String ignoreContentType;
    private int defaultTimeout = -1;
    

    public HttpProxyServlet()
    {
        keepHeaders = "true";
        disableAcceptEncoding = "false";
    }

    @Override
	public void log(String msg) {
		logger.info(msg);
	}

	@Override
	public void log(String message, Throwable t) {
		logger.error(message, t);
	}

	public void init() throws ServletException
    {
        hostName = getInitParameter(HOST_PARAM);
        if(hostName == null)
        {
            final String msg = "HttpProxyServlet needs a host in the parameter.";
			log(msg);
            throw new ServletException(msg);
        }
        proxyHost 				= getInitParameter(PROXY_HOST_PARAM);
        proxyPort 				= getInitParameter(PROXY_PORT_PARAM);
        rewriteHost 			= getInitParameter(REWRITE_HOST_PARAM);
        encoding 				= getInitParameter(ENCODING_PARAM);
        uri 					= normalizeUri(getInitParameter(URI_PARAM));
        keepHeaders 			= getInitParameter(HEADERS_PARAM);
        disableAcceptEncoding	= getInitParameter(GZIP_PARAM);
        ignoreContentType		= getInitParameter(IGNORE_CONTENT_TYPE_PARAM);
        
        final String timeout	= getInitParameter(TIMEOUT_PARAM);
        if( timeout != null ) {
        	try {
        		defaultTimeout = Integer.parseInt(timeout);
        	}
        	catch( NumberFormatException e ) {
        		log( String.format("error timeout [%s] parameter is not valid!", timeout));
        		defaultTimeout = -1;
        	}
        }
        
        if(keepHeaders == null)				keepHeaders = "true";
        if(disableAcceptEncoding == null)	disableAcceptEncoding = "false";
    }

	public String getURI() { return uri; }
	
	
    public void doDelete(HttpServletRequest httpservletrequest, HttpServletResponse httpservletresponse) throws ServletException, IOException
    {
        String queryString = httpservletrequest.getQueryString();
        String host = processRequestURI(httpservletrequest, hostName);

        host = addQuery(host, queryString);
        Hashtable<String,String> hashtable = null;
        
        if("true".equals(keepHeaders))
        {
            hashtable = new Hashtable<String,String>();
            getHeaders(httpservletrequest, hashtable);
            if("true".equals(rewriteHost))
            {
                hashtable.remove(HOST_PARAM);
                hashtable.remove("Host");
                hashtable.remove("HOST");
                hashtable.put("Host", getHostInfo(hostName));
            }
            if("false".equals(disableAcceptEncoding))
                hashtable.remove("ACCEPT-ENCODING");
            
            
        }
        GetPost getpost = new GetPost( Boolean.parseBoolean(ignoreContentType) );
        String result = getpost.doDelete(host, null, hashtable, defaultTimeout, proxyHost, proxyPort, encoding, httpservletrequest.getInputStream(), httpservletresponse);
        if(result != null)
        {
            int i = getpost.getErrorCode();
            if(i > 0)
                httpservletresponse.sendError(i, result);
            else
                httpservletresponse.sendError(503, result);
        }
    }

    public void doHead(HttpServletRequest httpservletrequest, HttpServletResponse httpservletresponse) 
        throws ServletException, IOException
    {
        String queryString = httpservletrequest.getQueryString();
        String host = processRequestURI(httpservletrequest, hostName);
        //Object obj = null;
        host = addQuery(host, queryString);
        Hashtable<String,String> hashtable = null;
        if("true".equals(keepHeaders))
        {
            hashtable = new Hashtable<String,String>();
            getHeaders(httpservletrequest, hashtable);
            if("true".equals(rewriteHost))
            {
                hashtable.remove(HOST_PARAM);
                hashtable.remove("Host");
                hashtable.remove("HOST");
                hashtable.put("Host", getHostInfo(hostName));
            }
            if("false".equals(disableAcceptEncoding))
                hashtable.remove("ACCEPT-ENCODING");
        }
        GetPost getpost = new GetPost(Boolean.parseBoolean(ignoreContentType));
        String result = getpost.doHead(host, null, hashtable, defaultTimeout, proxyHost, proxyPort, encoding, httpservletrequest.getInputStream(), httpservletresponse);
        if(result != null)
        {
            int errorCode = getpost.getErrorCode();
            if(errorCode > 0)
                httpservletresponse.sendError(errorCode, result);
            else
                httpservletresponse.sendError(503, result);
        }
    }

    public void doGet(HttpServletRequest httpservletrequest, HttpServletResponse httpservletresponse) throws ServletException, IOException
    {
        String queryString = httpservletrequest.getQueryString();
        String host = processRequestURI(httpservletrequest, hostName);
 
        host = addQuery(host, queryString);
        Hashtable<String,String> headerMap = null;
        
        if("true".equals(keepHeaders))
        {
            headerMap = new Hashtable<String,String>();
            getHeaders(httpservletrequest, headerMap);
            if("true".equals(rewriteHost))
            {
                headerMap.remove(HOST_PARAM);
                headerMap.remove("Host");
                headerMap.remove("HOST");
                headerMap.put("Host", getHostInfo(hostName));
            }
            if("false".equals(disableAcceptEncoding))
                headerMap.remove("ACCEPT-ENCODING");
        }
        GetPost getpost = new GetPost(Boolean.parseBoolean(ignoreContentType));
        String result = getpost.doAction(httpservletrequest.getMethod().toUpperCase(), host, null, headerMap, defaultTimeout, proxyHost, proxyPort, encoding, httpservletrequest.getInputStream(), httpservletresponse);
        if(result != null)
        {
            int errorCode = getpost.getErrorCode();
            if(errorCode > 0)
                httpservletresponse.sendError(errorCode, result);
            else
                httpservletresponse.sendError(503, result);
        }
    }

    @SuppressWarnings("unchecked")
	public void doPost(HttpServletRequest httpservletrequest, HttpServletResponse httpservletresponse)
        throws ServletException, IOException
    {
        String queryString = httpservletrequest.getQueryString();
        String host = processRequestURI(httpservletrequest, hostName);

        host = addQuery(host, queryString);
        Hashtable<String,String> hashtable = null;
        Hashtable<String,String> hashtable1 = new Hashtable<String,String>();
        Enumeration<String> enumeration = httpservletrequest.getParameterNames();
        do
        {
            if(!enumeration.hasMoreElements())
                break;
            String paramName = enumeration.nextElement();
            String as[] = httpservletrequest.getParameterValues(paramName);
            if(as != null && as.length > 0)
            {
                int i = 0;
                while(i < as.length) 
                {
                    hashtable1.put((new StringBuilder()).append(paramName).append("<").append(i).append(">").toString(), as[i]);
                    i++;
                }
            }
        } while(true);
        if("true".equals(keepHeaders))
        {
            hashtable = new Hashtable<String,String>();
            getHeaders(httpservletrequest, hashtable);
            if("true".equals(rewriteHost))
            {
                hashtable.remove(HOST_PARAM);
                hashtable.remove("Host");
                hashtable.remove("HOST");
                hashtable.put("Host", getHostInfo(hostName));
            }
            if("false".equals(disableAcceptEncoding))
                hashtable.remove("ACCEPT-ENCODING");
        }
        GetPost getpost = new GetPost(Boolean.parseBoolean(ignoreContentType));
        String result = getpost.doAction(httpservletrequest.getMethod().toUpperCase(), host, hashtable1, hashtable, defaultTimeout, proxyHost, proxyPort, encoding, httpservletrequest.getInputStream(), httpservletresponse);
        if(result != null)
        {
            int errorCode = getpost.getErrorCode();
            if(errorCode > 0)
                httpservletresponse.sendError(errorCode, result);
            else
                httpservletresponse.sendError(503, result);
        }
    }

    @SuppressWarnings("unchecked")
	public void doPut(HttpServletRequest httpservletrequest, HttpServletResponse httpservletresponse)
        throws ServletException, IOException
    {
        String queryString = httpservletrequest.getQueryString();
        String host = processRequestURI(httpservletrequest, hostName);

        host = addQuery(host, queryString);
        Hashtable<String,String> hashtable = null;
        Hashtable<String,String> hashtable1 = new Hashtable<String,String>();
        Enumeration<String> enumeration = httpservletrequest.getParameterNames();
        do
        {
            if(!enumeration.hasMoreElements())
                break;
            String paramName = enumeration.nextElement();
            String as[] = httpservletrequest.getParameterValues(paramName);
            if(as != null && as.length > 0)
            {
                int i = 0;
                while(i < as.length) 
                {
                    hashtable1.put((new StringBuilder()).append(paramName).append("<").append(i).append(">").toString(), as[i]);
                    i++;
                }
            }
        } while(true);
        if("true".equals(keepHeaders))
        {
            hashtable = new Hashtable<String,String>();
            getHeaders(httpservletrequest, hashtable);
            if("true".equals(rewriteHost))
            {
                hashtable.remove(HOST_PARAM);
                hashtable.remove("Host");
                hashtable.remove("HOST");
                hashtable.put("Host", getHostInfo(hostName));
            }
            if("false".equals(disableAcceptEncoding))
                hashtable.remove("ACCEPT-ENCODING");
        }
        GetPost getpost = new GetPost(Boolean.parseBoolean(ignoreContentType));
        String result = getpost.doPut(host, hashtable1, hashtable, defaultTimeout, proxyHost, proxyPort, encoding, httpservletrequest.getInputStream(), httpservletresponse);
        if(result != null)
        {
            int errorCode = getpost.getErrorCode();
            if(errorCode > 0)
                httpservletresponse.sendError(errorCode, result);
            else
                httpservletresponse.sendError(503, result);
        }
    }

    @SuppressWarnings("unchecked")
	private void getHeaders(HttpServletRequest httpservletrequest, Hashtable<String,String> hashtable)
    {
        String headerName;
        String headerValue;
        for(Enumeration<String> enumeration = httpservletrequest.getHeaderNames(); enumeration.hasMoreElements(); hashtable.put(headerName, headerValue))
        {
            headerName = enumeration.nextElement();
            headerValue = "";
            for(Enumeration<String> enumeration1 = httpservletrequest.getHeaders(headerName); enumeration1.hasMoreElements();)
            {
                if(headerValue.length() > 0)
                    headerValue = new StringBuilder().append(headerValue).append(",").toString();
                headerValue = new StringBuilder().append(headerValue).append((String)enumeration1.nextElement()).toString();
            }

        }

    }

    private String getHostInfo(String hostName)
    {
        String host = hostName;
        int i = host.indexOf("://");
        if(i > 0)
            host = host.substring(i + 3);
        i = host.indexOf("/");
        if(i > 0)
            host = host.substring(0, i);
        i = host.indexOf("?");
        if(i > 0)
            host = host.substring(0, i);
        i = host.indexOf("#");
        if(i > 0)
            host = host.substring(0, i);
        i = host.indexOf(";");
        if(i > 0)
            host = host.substring(0, i);
        return host;
    }

    private String addQuery(String hostName, String queryString)
    {
        if(queryString != null)
        {
            if(hostName.indexOf("?") < 0)
                return new StringBuilder().append(hostName).append("?").append(queryString).toString();
            else
                return new StringBuilder().append(hostName).append("&").append(queryString).toString();
        } else
        {
            return hostName;
        }
    }

    
    private String processRequestURI( HttpServletRequest httpservletrequest, String host ) {
    	
        if(getURI() != null)
        {
        	String uri = getURI();
        	
            String requestURI = httpservletrequest.getRequestURI();
            if(requestURI != null)
            {
                if(!requestURI.startsWith(uri)) {
                    //requestURI = null;
                    logger.warn( String.format("parameter 'uri' [%s] doesn't match with request URI [%s]. uri ignored!", uri, requestURI));
                    uri = "/"; 
                }
                
                if(uri.length() >= requestURI.length()) {
                    //requestURI = null;
                    logger.warn( String.format("parameter 'uri' [%s] is longer than request URI [%s]. uri ignored!", uri, requestURI));
                    uri = "/"; 
                }
                
                
                requestURI = requestURI.substring(uri.length());
                
                if(requestURI != null)
                    host = addUri(host, requestURI);
            }
        }
        
        return host;
   	
        /*
        if(uri != null)
        {
            uri = normalizeUri(uri);
            String requestURI = httpservletrequest.getRequestURI();
            if(requestURI != null)
            {
                if(!requestURI.startsWith(uri))
                    requestURI = null;
                else
                if(uri.length() >= requestURI.length())
                    requestURI = null;
                else
                    requestURI = requestURI.substring(uri.length());
                if(requestURI != null)
                    host = addUri(host, requestURI);
            }
        }

         */
    }
    
    private String addUri(String host, String requestURI)
    {
        if(requestURI == null)			return host;
        if(requestURI.length() == 0)	return host;
        if(requestURI.equals("/"))		return host;
        
        String s2 = requestURI;
        
        if(s2.charAt(0) == '/') s2 = s2.substring(1);
        if(s2.length() == 0) return host;
        
        String s3 = "";
        String s4 = host;
        int i = s4.indexOf("?");
        if(i > 0)
        {
            if(i < s4.length() - 1) s3 = s4.substring(i + 1);
            s4 = s4.substring(0, i);
        }
        if(!s4.endsWith("/")) s4 = (new StringBuilder()).append(s4).append("/").toString();
        s4 = (new StringBuilder()).append(s4).append(s2).toString();
        if(s3.length() > 0) s4 = (new StringBuilder()).append(s4).append("?").append(s3).toString();
        
        return s4;
    }

    protected String normalizeUri(String uri)
    {
    	if( uri==null ) {
    		logger.warn( "parameter 'uri' is null");
    		return null;
    	}
    	
        int i = uri.indexOf("*");
        if(i < 0)
            return uri;
        if(i == 0)
            return "/";
        else
            return uri.substring(0, i);
    }

}
